#include "XmlConfig.h"

#ifdef _WIN32
const char* TiXmlNodeEx::GetEncoding(const char* file)
{
    TiXmlNode* node = Identify(file, TIXML_ENCODING_UNKNOWN);

    if (node)
    {
        TiXmlParsingData* data = NULL;
        file = node->Parse(file, data, TIXML_ENCODING_UNKNOWN);
        LinkEndChild(node);
    }

    TiXmlDeclaration* dec = node->ToDeclaration();

    if (dec)
    {
        return dec->Encoding();
    }
    else
        return NULL;
}

const char* TiXmlNodeEx::ParseData(const char* data)
{
    const unsigned char* pU = (const unsigned char*)data;

    if (*(pU + 0) && *(pU + 0) == 0xefU
        && *(pU + 1) && *(pU + 1) == 0xbbU
        && *(pU + 2) && *(pU + 2) == 0xbfU)
    {
        data = SkipWhiteSpace(data, TIXML_ENCODING_UTF8);
    }

    return data;
}
#endif

bool XmlConfig::Open(const char *fileName)
{
    file = fileName;

    if (!document.LoadFile(fileName))
    {
        rootElem = 0;
        return false;
    }

    rootElem = document.RootElement();

    return true;
}

const char* XmlConfig::Get(const char *element, const char *attribute, const char *defaultValue)
{
    if (!rootElem)
        return defaultValue;

    TiXmlElement* elem = rootElem->FirstChildElement(element);
    if (!elem)
        return defaultValue;

    const char *content = elem->Attribute(attribute);

    if (content)
        return content;
    else
        return defaultValue;
}

int XmlConfig::GetIntValue(const char *element, const char *attribute, int defaultValue)
{
    if (!rootElem)
        return defaultValue;

    TiXmlElement* elem = rootElem->FirstChildElement(element);
    if (!elem)
        return defaultValue;
    
    int value;
    if (elem->QueryIntAttribute(attribute, &value) != TIXML_SUCCESS)
        return defaultValue;
    else
        return value;
}

double XmlConfig::GetDoubleValue(const char *element, const char *attribute, double defaultValue)
{
    if (!rootElem)
        return defaultValue;

    TiXmlElement* elem = rootElem->FirstChildElement(element);
    if (!elem)
        return defaultValue;

    double value;
    if (elem->QueryDoubleAttribute(attribute, &value) != TIXML_SUCCESS)
        return defaultValue;
    else
        return value;
}

bool XmlConfig::Set(const char *element, const char *attribute, const char *value)
{
    if (!rootElem)
        return false;

    TiXmlElement* elem= rootElem->FirstChildElement(element);
    if (!elem)
        return false;

    elem->SetAttribute(attribute, value);

    return true;
}

bool XmlConfig::Save(const char *fileName)
{
    return document.SaveFile(fileName);
}

#ifdef _WIN32
const char* XmlConfig::GetEncoding()
{
    FILE* fp = 0;
    TiXmlNodeEx xml_node;
    long length = 0;
    if (fopen_s(&fp, file, "rb"))
    {
        return 0;
    }

    fseek(fp, 0, SEEK_END);
    length = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    if (length <= 0)
    {
        return 0;
    }

    char* buf = new char[length + 1];
    buf[0] = 0;
    if (fread(buf, length, 1, fp) != 1)
    {
        delete[] buf;
        return 0;
    }

    if (!xml_node.GetEncoding(xml_node.ParseData(buf)))
    {
        return 0;
    }

    const char* temp = xml_node.GetEncoding(xml_node.ParseData(buf));
    char* encoding = new char[strlen(xml_node.GetEncoding(xml_node.ParseData(buf))) + 1];
    strcpy_s(encoding, strlen(temp) + 1, temp);

    return encoding;
}
#endif
